/**
 * 导入前置依赖
 */
/* ---------------------------------------------------------------------
 *                           Require modules
 * --------------------------------------------------------------------- */
// Express
const express = require("express");
const app = express();

const path = require("path");

const http = require("http");
const server = http.createServer(app);

// Morgan
const morgan = require("morgan");
// Session
const session = require("express-session");
// Enable session store in MongoDB
const MongoDBStore = require("connect-mongodb-session")(session);
const bodyParser = require("body-parser");

// Mongoose
const mongoose = require("mongoose");
const expressJwt = require("express-jwt");
const jwt = require("jsonwebtoken");
const {
  accessLogStream,
  PORT,
  DATA_BASE,
  HOST_NAME,
} = require("./src/server/utilities/common.js");
const {
  jwtConfig,
  authenticateToken,
} = require("./src/server/utilities/jwtUtils.js");
//TODO 如果有其他的请求应该先进行jwt验证
mongoose.Promise = require("bluebird");

// Obtain the user server interface
const userRouter = require("./src/server/user.js");
const lawRouter = require("./src/server/law.js");
const searchRouter = require("./src/server/search.js");
const sessionSecret = process.env.SESSION_SECRET || "PXU Lily Web";

// 初始化数据
const initSearchData = require("./src/db/initSearchData.js");

// 数据库连接
mongoose
  .connect(DATA_BASE)
  .then(async () => {
    console.log("数据库连接成功");

    // 初始化搜索数据
    await initSearchData();
  })
  .catch((err) => {
    console.error("数据库连接失败：", err);
  });

/* ---------------------------------------------------------------------
 *                           Middle layer
 * --------------------------------------------------------------------- */
// One day
const COOKIE_MAX_AGE = 24 * 60 * 60 * 1000;
// const COOKIE_MAX_AGE = 15 * 60 * 1000;

// Session
// Enable session store in MongoDB
const sessionStore = new MongoDBStore({
  uri: DATA_BASE,
  collection: "usersessions",
});

const sessionMiddleware = session({
  secret: sessionSecret,
  resave: false,
  saveUninitialized: false,
  // Enable session store in MongoDB
  store: sessionStore,
  cookie: {
    sameSite: "lax",
    httpOnly: true,
    secure: false,
    maxAge: COOKIE_MAX_AGE,
  },
});
app.use(sessionMiddleware);
// Express static module
app.use(express.static("dist"));
app.use(express.static("public"));

// Body parser
app.use(bodyParser.json());
//配置jwt中间件
//TODO目前登录和注册是写在了/user里面，所以排除了/user，可能以后要换/api
app.use(
  expressJwt
    .expressjwt({ secret: jwtConfig.jwtSecretKey, algorithms: ["HS256"] })
    .unless({ path: [/^\/user/] })
);

// Logging facility
app.use(morgan("common", { stream: accessLogStream }));

// jwt错误提示
app.use(function (err, req, res, next) {
  if (err.name === "UnauthorizedError" && err.message === "invalid token") {
    res.status(401).send("无效的token");
  }
  if (err.name === "UnauthorizedError" && err.message === "jwt expired") {
    res.status(401).send("token过期");
  }
  next();
});

/* ---------------------------------------------------------------------
 *                           URL /user/*
 * --------------------------------------------------------------------- */
app.use("/user", userRouter);

/* ---------------------------------------------------------------------
 *                           URL /law/*
 * --------------------------------------------------------------------- */
app.use("/law", authenticateToken, lawRouter);

/* ---------------------------------------------------------------------
 *                           URL /search/*
 * --------------------------------------------------------------------- */
app.use("/search", authenticateToken, searchRouter);

/* ---------------------------------------------------------------------
 *                           URL /*
 * --------------------------------------------------------------------- */
//获取测试数据
app.get("/test/law-data", function (request, response) {
  response.sendFile(path.join(__dirname, "public", "law.json"));
});

// 接收前端的请求，并返回index.html页面
app.get("/*", function (request, response) {
  response.sendFile(path.join(__dirname, "dist", "index.html"), function (err) {
    if (err) {
      response.status(500).send(err);
    }
  });
});

// 启动后端服务
server.listen(PORT, () => {
  let port = server.address().port;
  console.log(`Server running on ${HOST_NAME}:${port}`);
});
